﻿using System;
using System.Web.Mvc;
using System.Web.Security;
using GiveAQuiz.Data;
using GiveAQuiz.Web.Authentication;
using GiveAQuiz.Web.Membership;
using GiveAQuiz.Web.Messenger;
using GiveAQuiz.Web.Models;

namespace GiveAQuizSite.Controllers
{
  /// <summary>
  /// This class serves as a Controller for actions dealing 
  /// with Account management.
  /// </summary>
  [HandleError]
  public class AccountController : AuthenticationController
  {
    /// <summary>
    /// Create a new instance of the AccountController.
    /// </summary>
    /// <param name="repository">The QuizRepository.</param>
    /// <param name="formsAuth">The Forms Authentication service.</param>
    /// <param name="membershipService">The Account Membership service.</param>
    /// <param name="acctMessenger">The Account Messenger service.</param>
    public AccountController(IQuizRepository repository,
      IFormsAuthentication formsAuth, 
      IMembershipService membershipService,
      IAccountMessenger acctMessenger)
      : base(repository, formsAuth, membershipService, acctMessenger)
    {
    }

    /// <summary>
    /// ~/Account/LogOn
    /// </summary>
    /// <param name="ReturnUrl">The URL to return to after a successful
    /// log on.</param>
    /// <returns>~/Views/Account/LogOn.aspx</returns>
    public ActionResult LogOn(string ReturnUrl)
    {
      ViewData["ReturnUrl"] = ReturnUrl ?? String.Empty;
      return View();
    }

    /// <summary>
    /// ~/Account/LogOn
    /// </summary>
    /// <param name="model">The form parameters bound to 
    /// the LogOnViewModel object.</param>
    /// <returns>~/Views/Index/Home.aspx</returns>
    [AcceptVerbs(HttpVerbs.Post)]
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
        Justification = "Needs to take same parameter type as Controller.Redirect()")]
    public ActionResult LogOn(LogOnViewModel model)
    {
      // validate the input by calling LogOnValidator
      if (!ModelState.IsValid)
      {
        return View(); // back to the original page
      }

      // authenticate against the MembershipService
      if (!MembershipService.ValidateUser(model.UserName, model.Password))
      {
        ModelState.AddModelError("_FORM", "The username or password provided is incorrect.");
        return View();
      }
      else
      {
        // sign in
        FormsAuth.SignIn(model.UserName, model.IsRemembered);

        if (!String.IsNullOrEmpty(model.ReturnUrl))
        {
          // send back to the return url
          return Redirect(model.ReturnUrl);
        }
        else
        {
          // home
          return RedirectToAction("Index", "Home");
        }
      }
    }

    /// <summary>
    /// ~/Account/LogOff
    /// </summary>
    /// <returns>~/Views/Home/Index.aspx</returns>
    public ActionResult LogOff()
    {
      // sign out
      FormsAuth.SignOut();
      return RedirectToAction("Index", "Home");
    }    

    /// <summary>
    /// ~/Account/ChangePassword
    /// </summary>
    /// <returns>~/Views/Account/ChangePassword.aspx</returns>
    [Authorize]
    public ActionResult ChangePassword()
    {
      ViewData["PasswordLength"] = MembershipService.MinPasswordLength;

      return View();
    }

    /// <summary>
    /// ~/Account/ChangePassword
    /// </summary>
    /// <param name="model">The form parameters bound to a ChangePasswordViewModel.</param>
    /// <returns>~/Views/Account/ChangePasswordSuccess.aspx</returns>
    [Authorize]
    [AcceptVerbs(HttpVerbs.Post)]
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",
        Justification = "Exceptions result in password not being changed.")]
    public ActionResult ChangePassword(ChangePasswordViewModel model)
    {
      ViewData["PasswordLength"] = MembershipService.MinPasswordLength;

      // calls ChangePasswordValidator
      if (!ModelState.IsValid)
      {
        return View();
      }

      try
      {
        if (MembershipService.ChangePassword(User.Identity.Name, model.CurrentPassword, model.NewPassword))
        {
          return RedirectToAction("ChangePasswordSuccess"); // success
        }
        else
        {
          ModelState.AddModelError("_FORM", "The current password is incorrect or the new password is invalid.");
          return View();
        }
      }
      catch
      {
        ModelState.AddModelError("_FORM", "The current password is incorrect or the new password is invalid.");
        return View();
      }
    }

    /// <summary>
    /// ~/Account/ChangePasswordSuccess
    /// </summary>
    /// <returns>~/Views/Account/ChangePasswordSuccess.aspx</returns>
    public ActionResult ChangePasswordSuccess()
    {
      return View();
    }

    /// <summary>
    /// ~/Account/ResetPassword
    /// </summary>
    /// <returns>~/Views/Account/ResetPassword.aspx</returns>
    public ActionResult ResetPassword()
    {
      return View();
    }

    /// <summary>
    /// ~/Account/ResetPassword
    /// </summary>
    /// <param name="model">The form parameters bound to a 
    /// ResetPasswordViewModel.</param>
    /// <returns>~/Views/Account/ResetPassword.aspx</returns>
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult ResetPassword(ResetPasswordViewModel model)
    {
      // calls ResetPasswordValidator
      if (!ModelState.IsValid)
      {
        return View("ResetPassword", model);
      }
      MembershipUser user;
      if (!String.IsNullOrWhiteSpace(model.UserName))
      {
        // find by user name
        user = MembershipService.GetUser(model.UserName);
      }
      else
      {
        // find by email
        user = MembershipService.GetUserByEmail(model.Email);
      }

      if ( user != null ) 
      {
        string newPassword = MembershipService.ResetPassword(user.UserName);
        AccountMessenger.SendPasswordResetMessage(user, newPassword);
        ViewData["NewPassword"] = newPassword;
        return View("ResetPasswordSuccess");
      }

      ModelState.AddModelError("_FORM", "No matching User was found");
      return View("ResetPassword", model);      
    }



  }
    
}
